Cheap'n'nasty transfers

TAD

Introduction

Adok's recent article and ICQ chat about Amiga emulators has got my brain ticking over again (I know, that is no easy task. *grin*). He mentioned about the problems of transferring data from one machine onto another and as most people go directly for a serial (null modem) link, I thought I would talk about my own parallel linkup method and some basic, easy-to-understand explanations about communication.

So if you have ever wondered about how to transfer data quickly using nothing more than an adapted parallel printer cable and a few lines of 80386 and 68000 assembly code, then read on...

Why bother and what is PDS?

Many years ago I wanted to create a simple development system, something along the lines of PDS (Programmer's Development System). A few years earlier PDS had been a very popular phrase and had coders drooling, mostly because it made writing code so much easier (especially for large projects on consoles or other ugly OS machines). Whereas proper PDS systems used a PC linked to the 'target' machine, I only had an Amiga A500 and an old Atari ST. Without ever reading a data communications book or having the vital electronics knowledge, I did manage to get a working PDS-like system up and run surpassingly quickly.

The basic idea behind PDS is that you only edit/compile your code on ONE machine and only ever EXECUTE the code on the other machine. The advantage is that you can look at your code while your program is being tested on the target machine. If the program crashes then your source code is unaffected, you don't need to reload your editor, compiler, IDE etc.. you only have to reboot the target machine and load the DOWNLOADER software.

The Parallel Port

I chose the parallel port because of its high speed and ease of access. A serial connection is okay, but on those 16-bit computers it would have taken ages to transfer anything larger than a 10kb file. Remember, parallel is more than 8 times faster than serial because you can send a whole byte at a time.

Firstly I took an old 2m printer cable and replaced the printer plug with another 25-pin D-type connector. You could build an entire cable from scratch, but it's quicker and cheaper to buy a printer cable and adapt it. The wiring below is pretty much the bare minimum (this is due to the basic Atari ST hardware). All you need are the 8 data-lines and swap the Strobe <--> Busy lines over so that the Strobe from one machine goes to the Busy of the other and vice-versa.

In fact the Atari ST port Busy signal line was totally screwed. But it was still possible to transfer 1 meg from the ST up to my PC in around 25 seconds.

                   busy      <--------- data line ------->  strobe
            13      11       9   8   7   6   5   4   3   2   1
        \    o   o   o   o   o   o   o   o   o   o   o   o   o     /
  PC      \          ³       ³   ³   ³   ³   ³   ³   ³   ³   ³   /
            \  o   o ³ o   o ³ o ³ o ³ o ³ o ³ o ³ o ³ o ³ o ³ /
                     ³       ³   ³   ³   ³   ³   ³   ³   ³   ³
                     ³       ³   ³   ³   ³   ³   ³   ³   ³   ³
                     ³   ÚÄÄij Äij Äij Äij Äij Äij Äij Äij ÄÄÙ
                     ³   ³   ³   ³   ³   ³   ³   ³   ³   ³
                     ÀÄÄÄÄÄÄij Äij Äij Äij Äij Äij Äij Äij ÄÄ¿
                     ÚÄÄÄÙ   ³   ³   ³   ³   ³   ³   ³   ³   ³
                     ³       ³   ³   ³   ³   ³   ³   ³   ³   ³ strobe
            13       ³       ³   ³   ³   ³   ³   ³   ³   ³   ³ 1
        \    o   o   o   o   o   o   o   o   o   o   o   o   o     /
  ST      \        busy                                          /
            \  o   o   o   o   o   o   o   o   o   o   o   o   /

Sync, Strobe and Busy

Okay, now you've got a modified printer cable you need to write the software. In order to do this you need to think about sync, handshake, strobe and busy (gee, sounds like a Freemason disco party game ;)). You need to think in terms of time. I will describe the one-way strobe method because its the easiest. It involves using the 8 Data-lines and the 1 Strobe-line. The Strobe line acts like a timing signal, like the red and green at the traffic lights. We need to tell the target machine when a new byte has been written to the 8 data-lines.

Sync      byte 1          byte 2          byte 3          byte 4
        a   b   c       a   b   c       a   b   c       a   b   c
hi     ÚÄÄÄÄÄÄÄ¿       ÚÄÄÄÄÄÄÄ¿       ÚÄÄÄÄÄÄÄ¿       ÚÄÄÄÄÄÄÄ¿    
       ³       ³       ³       ³       ³       ³       ³       ³ 
       ³       ³       ³       ³       ³       ³       ³       ³
       ³       ³       ³       ³       ³       ³       ³       ³
lo   ÄÄÙ       ÀÄÄÄÄÄÄÄÙ       ÀÄÄÄÄÄÄÄÙ       ÀÄÄÄÄÄÄÄÙ       À....
                   d               d               d
      time ---------------------->

The above time diagram shows the 4 stages of data transmission in terms of the Stobe-->Busy signal (the hi, lo). Stage 'a' 'b' and 'c' happen on the sender machine (in this case the Atari ST). Stage 'd' happens on the target receiver machine (in this case the PC).

  Stage 'a'   Sender: Set Strobe high ----> Target: sees Busy=high
  stage 'b'   Sender: Write byte to Data-lines
  stage 'c'   Sender: Set Strobe low  ----> Target: sees Busy=low
  stage 'd'   Target: Reads byte from Data-lines

As you can see we can keep both the Sender and Target machine in phrase by means of our 'sync' signal. The sync signal is sent from the Sender ('Strobe' pin #1) and is received by the Target ('Busy' pin #11). The job of the sync is to keep both machines in phase (so you know when a new data byte has been transmitted) and also to say when a valid byte is on the data-lines.

You should notice that the hi, lo states tell both sides when it is safe to write (sender) a new byte and when it is safe to read (target) a new byte. It's like the traffic lights at a junction, when one direction is red the other is green. This prevents any collision in terms of data.

Some nice 68000 code

Here is a snippet of 68000 source code which will transmit a block of data using the above strobe-busy sync method. It doesn't bother about checking if the target machine is ready or not. It was written for the Atari ST, which has its parallel port registers on the sound chip. The 'MOVEP' instruction does a similar thing to the 80x86 'OUT DX,AX' instruction, except the 68000 has NO ports, it is all memory based.

;* Download(A0) Length(d0) *
download:
        sub.l   a2,a2
        move.w  #$07c0,d1
        movep.w d1,SNDCHIP(a2)          ;    Port A & B = output mode
        move.w  #$0e07,d2               ;    strobe HIGH - normal
dl_LOOP:
        bsr.s   dl_PULSE                ;(a) strobe HIGH (busy) + delay

        move.w  #$0F00,d1
        move.b  (a0)+,d1
        movep.w d1,SNDCHIP(a2)          ;(b) byte --> port B

        bsr.s   dl_PULSE                ;(c) strobe LOW (ready) + delay
        subq.l  #1,d0
        bne.s   dl_LOOP
                                        ;    final HIGH (I'm Busy...)
dl_PULSE:
        movep.w d2,SNDCHIP(a2)          ;    SetStrobe(d2)
        rol.l   #8,d1                   ;    a lame, short delay
        move.w  d0,COLOR0(a2)           ;    some horrible turbo fx
        bchg    #5,d2                   ;    toggle Strobe Hi/Lo value
        rts

Yep, that's about 48 bytes of 68000 code. It definitely works because I've used it to take a memory snapshot of a game and upload it onto the PC so I could run it using the PacifiST emulator.

Some 80386 pmode code

And here is the corresponding 80386 Protected-mode code to upload a block of data from the parallel port. If you have any problems reading data from your PC parallel port then try port+00h or port+03h.

PPORT           equ     278h            ; parallel port base
PPORT_STATUS    equ     PPORT+1
PPORT_INPUT     equ     PPORT+3         ; was +3

KEY_PORT        equ     60h             ; keyboard data port

SETBORDER       MACRO   colr
        mov     dx,3C0h
        mov     al,31h
        out     dx,al
        mov     al,colr
        out     dx,al
                ENDM

;* Upload into[ES:EDI] length(ECX) *
upload:
        mov     dx,3DAh
        in      al,dx                   ; clear flip-flop

;-------------------- wait for initial busy (HIGH) ---------------------
        SETBORDER 000111b               ; grey
        mov     dx,PPORT_STATUS
up_SYNC:
        in      al,KEY_PORT
        cmp     al,81h
        jz      short up_BREAK          ; ESC ?
        in      al,dx
        test    al,80h
        jz      short up_SYNC           ; not busy ?

;------------------------- now begin upload ----------------------------
        SETBORDER 010010b               ; green
up_LOOP:
        mov     dx,PPORT_STATUS
up_BUSY:
        in      al,KEY_PORT
        cmp     al,81h
        jz      short up_BREAK          ; ESC ?
        in      al,dx
        test    al,80h
        jnz     short up_BUSY           ; wait until ready ...

        mov     dx,PPORT_INPUT
        in      al,dx                   ; read byte from Data-lines
        stosb                           ; byte --> buffer
        mov     ah,al

        SETBORDER ah                    ; nice turbs

        mov     dx,PPORT_STATUS
up_READY:
        in      al,KEY_PORT
        cmp     al,81h
        jz      short up_BREAK          ; ESC ?
        in      al,dx
        test    al,80h
        jz      short up_READY          ; wait until busy again ...

        dec     ecx
        jnz     short up_LOOP

        SETBORDER 000000b               ; black = okay
        clc
        ret

up_BREAK:
        lea     edx,breaktxt
        call    conmess                 ; display 'User break' message

        SETBORDER 100100b               ; red = error/break
        stc
        ret

Getting started by yourself

Okay, so none of you will probably ever want to upload data from an ancient Atari-ST to the PC, but you might want to transfer data from the Amiga or another PC, in which can you should be able to adapt the method to suit your needs. Here are some tips which might help you create your own uploader and downloader software.

(1) Write a test program to display ALL the port registers.

(2) Write a test program to toggle the Strobe and place test values on the Data-lines to check your cable.

(3) Examine the default values (after reboot) of the busy signal.

(4) Keep read and write stages on opposite hi/lo states.

(5) When downloading PC --> Amiga write 00h to Data-lines when you have finished, otherwise when you reboot the Amiga will Guru because it thinks the parallel port is broken.

(6) Some old PCs don't allow reading of the Data-lines in which case you need to use a 'LapLink' style cable. This uses a nibble transfer method using 5 status lines instead of the data-lines to read data.

(7) Be careful of SPP, EPP and ECP parallel ports (try reading from port+03h if port+00h gives no data).

Final thought.

Oh well, this might be of interest to someone out there. You can have some fun with parallel cables and trying to optimise your machines for maximum transfer speed. With most new PCs you now have DMA driven ECP (Enhanced Character Port) ports which often some really nice speeds without having to bother the CPU too much. But then again, if you want speed then perhaps the USB is worth looking at for PC-2-PC communication.

And yeah, if you need to copy gigs of data from one PC to another, then please, remove the HD, plug it in place of a CD-ROM/DVD drive and watch those bits really zoom along.

Happy down/uploading!

TAD